﻿using Blog.Core.Common;
using Microsoft.Extensions.DependencyInjection;
using SqlSugar;
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations.Schema;
using System.ComponentModel.DataAnnotations;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Blog.Common.Helper;
using System.Data;
using System.Reflection;
using Blog.Models.Entitys;
using log4net;

namespace Blog.Framework.Extension
{
    public static class SqlsugarSetup
    {
        private static readonly ILog _logger = LogManager.GetLogger(typeof(SqlsugarSetup));
        public static void AddSqlsugarSetup(this IServiceCollection services)
        {
            //注册上下文：AOP里面可以获取IOC对象，如果有现成框架比如Furion可以不写这一行
            services.AddHttpContextAccessor();
            //注册SqlSugar用AddScoped
            services.AddScoped<ISqlSugarClient>(it =>
            {
                ConnectionConfig connectionConfig = new ConnectionConfig();

                connectionConfig.ConnectionString = AppSettings.App("Db", "ConnStr");
                connectionConfig.DbType = (SqlSugar.DbType)AppSettings.GetValue<int>("Db", "DbType");
                connectionConfig.IsAutoCloseConnection = true;
                connectionConfig.LanguageType = LanguageType.Chinese;
                connectionConfig.ConfigureExternalServices = new ConfigureExternalServices()
                {
                    //实体和表的对应关系
                    EntityNameService = (type, entity) =>
                    {
                        entity.DbTableName = StringHelper.CamelToUnderline(type.Name);
                    },
                    //属性和列的对应关系
                    EntityService = (property, column) =>
                    {
                        column.DbColumnName = StringHelper.CamelToUnderline(property.Name);

                        /***高版C#写法***/
                        //支持string?和string  
                        if (column.IsPrimarykey == false && new NullabilityInfoContext()
                         .Create(property).WriteState is NullabilityState.Nullable)
                        {
                            column.IsNullable = true;
                        }
                    },
                };

                SqlSugarClient sqlSugarClient = new SqlSugarClient(connectionConfig, db =>
                {
                    db.Aop.OnLogExecuting = (sql, pars) =>
                    {
                        //Console.WriteLine(sql);//输出sql,查看执行sql 性能无影响

                        //获取原生SQL推荐 5.1.4.63  性能OK
                        //UtilMethods.GetNativeSql(sql, pars);

                        //获取无参数化SQL 对性能有影响，特别大的SQL参数多的，调试使用
                        _logger.Info(UtilMethods.GetSqlString(SqlSugar.DbType.SqlServer, sql, pars));

                    };
                });

                if (AppSettings.GetValue<bool>("Db", "AutoCreateDatabase", "Enable"))
                {
                    bool isCache = AppSettings.GetValue<bool>("Db", "AutoCreateDatabase", "IsCache");
                    AutoCreateDatabaseTable(sqlSugarClient, isCache);
                }
                return sqlSugarClient;
            });
        }

        /// <summary>
        /// 自动建库建表
        /// </summary>
        /// <param name="sqlSugarClient"></param>
        /// <param name="isCache"></param>
        /// <exception cref="NotImplementedException"></exception>
        private static void AutoCreateDatabaseTable(SqlSugarClient sqlSugarClient, bool isCache = true)
        {
            if (sqlSugarClient.CurrentConnectionConfig.DbType == SqlSugar.DbType.Oracle)
            {
                throw new Exception("Oracle不支持创建数据库！");
            }

            //创建数据库 此方法会自动判断数据库是否存在
            sqlSugarClient.DbMaintenance.CreateDatabase();

            //获取到实体类的集合
            Assembly? assembly = Assembly.GetAssembly(typeof(BaseEntity));

            //获取到表的实体映射集合
            Type[] tableTypes = assembly!.GetTypes().Where(it => it.IsClass && it.GetCustomAttribute<SugarTable>() != null).ToArray();


            foreach (Type tableType in tableTypes)
            {
                string tableName = StringHelper.CamelToUnderline(tableType.Name);
                //不存在这张表
                if (!sqlSugarClient.DbMaintenance.IsAnyTable(tableName, isCache))
                {
                    //创建表
                    sqlSugarClient.CodeFirst.InitTables(tableType);
                }
            }

        }
    }
}
